/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.ext.zul;

import cn.easyplatform.utils.SerializationUtils;
import cn.easyplatform.web.ext.Cacheable;
import cn.easyplatform.web.ext.ZkExt;
import org.zkoss.lang.Strings;
import org.zkoss.zk.au.AuRequest;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Bandbox;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class Actionbox extends Bandbox implements ZkExt, Cacheable {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    /**
     * 初始逻辑，处理相关的映射
     */
    private String _mapping;

    /**
     * 标题
     */
    private String _title;

    /**
     * 当输入值时是否自动匹配
     */
    private boolean _autocomplete;

    /**
     * SWIFT tag
     */
    private String _for;

    /**
     * 显示的位置 center|nocenter|left|right|top|bottom|parent
     * 可以组合:"left,center"表示靠左中间
     */
    private String _position = "center";

    /**
     * 打开窗口的宽度
     */
    private String _panelWidth;

    /**
     * 打开窗口的高度
     */
    private String _panelHeight;

    /**
     * 对应参数DATALIST的id
     */
    private String _entity;

    /**
     * 每一页的笔数
     */
    private int _pageSize = 20;

    /**
     * 不可视的列名称，Header.name,多个用逗号分隔
     */
    private String _invisibleColumns;

    /**
     *
     */
    private boolean _sizedByContent;

    /**
     * 分组名称：参考参数Group.name
     */
    private String _group;

    /**
     * 排序，如果值不为空，替找list参数中的排序栏位
     */
    private String _orderBy;

    /**
     * 栏位之间形成的层级结构，由2个栏位组成,第1个层级字段，第2个是父层字段
     */
    private String _levelBy;

    /**
     * 显示行数
     */
    private boolean _showRowNumbers;

    /**
     * 条件
     */
    private String _condition;

    /**
     * 是否显示分组笔数
     */
    private boolean _showGroupCount;

    /**
     * 是否显示查询面板
     */
    private boolean _showPanel = true;

    /**
     * 冻结的列数，从左到右开始
     */
    private int _frozenColumns;

    /**
     * 是否可以导出文件
     */
    private boolean _export = false;

    /**
     * 是否显示选择所有
     */
    private boolean _checkall;

    /**
     * 是否可选择
     */
    private boolean _checkmark;

    /**
     * 是否可多选
     */
    private boolean _multiple;

    /**
     * 列表间隔行风格
     */
    private String _oddRowSclass;

    /**
     * 是否填充右边空余空间
     */
    private boolean _span;

    /**
     * 列头可否调整大小
     */
    private boolean _sizable = true;

    /**
     * 分页组件是否显示详细信息
     */
    private boolean _pagingDetailed = true;

    /**
     * 分页组件是否自动显示
     */
    private boolean _pagingAutohide = true;

    /**
     * 分页组件显示模式
     */
    private String _pagingMold;

    /**
     * 分页组件显示style
     */
    private String _pagingStyle;

    /**
     * 行风格
     */
    private String _rowStyle;

    /**
     * 头部风格
     */
    private String _headStyle;

    /**
     *
     */
    private String _auxHeadStyle;

    /**
     * 底部风格
     */
    private String _footStyle;

    /**
     * 冻结头部风格
     */
    private String _frozenStyle = "background: #dfded8";

    /**
     * 显示标签值的栏位
     */
    private Object _realValue;

    /**
     * 当多选时保存的值类型:array|string
     */
    private String _valueType = "array";

    /**
     * 当多选时保存的值类型是string时值的分隔符
     */
    private String _separator = ",";

    /**
     * 是否使用组合显示，一个value，一个label,此时mapping给两个栏位名称
     */
    private boolean _combo = false;

    /**
     * 当combo为true时，定义查询语句
     */
    private String _comboQuery;

    /**
     * 显示的名称
     */
    private String _label;

    /**
     * 是否使用自定义查询的数据作为记录
     */
    private boolean _useQueryResult = true;

    /**
     * 初始脚本
     */
    private String _init;

    /**
     * 过滤表达式,target一定存在
     */
    private String _filter;

    /**
     * 初始打开的层次
     */
    private int _depth;

    /**
     * 是否使用session缓存
     */
    private boolean _cache;

    /**
     * 当pageSize大于0，fetchAll为true，表示获取所有的数据，不需要分页，使用本身的分页
     */
    private boolean _fetchAll;

    /**
     * 当checkall为true时选择的层次，往下打开层次
     */
    private int _checkDepth;

    public int getCheckDepth() {
        return _checkDepth;
    }

    public void setCheckDepth(int checkDepth) {
        this._checkDepth = checkDepth;
    }

    /**
     * @return the fetchAll
     */
    public boolean isFetchAll() {
        return _fetchAll;
    }

    /**
     * @param fetchAll the fetchAll to set
     */
    public void setFetchAll(boolean fetchAll) {
        this._fetchAll = fetchAll;
    }

    public boolean isCache() {
        return _cache;
    }

    public void setCache(boolean cache) {
        this._cache = cache;
    }

    /**
     * @return the depth
     */
    public int getDepth() {
        return _depth;
    }

    /**
     * @param depth the depth to set
     */
    public void setDepth(int depth) {
        this._depth = depth;
    }

    public String getFilter() {
        return _filter;
    }

    public void setFilter(String filter) {
        this._filter = filter;
    }

    public String getLabel() {
        return _label;
    }

    public void setLabel(String label) {
        if (isCombo())
            this.setValue(label);
        this._label = label;
    }

    public String getValueType() {
        return _valueType;
    }

    public String getSeparator() {
        return _separator;
    }

    public void setValueType(String valueType) {
        if (!"array".equals(valueType) && !"string".equals(valueType))
            throw new WrongValueException((new StringBuilder())
                    .append("Illegal valueType: ").append(valueType).toString());
        this._valueType = valueType;
    }

    public void setSeparator(String separator) {
        this._separator = separator;
    }

    public boolean isCombo() {
        return _combo;
    }

    public String getComboQuery() {
        return _comboQuery;
    }

    public void setCombo(boolean combo) {
        this._combo = combo;
    }

    public void setComboQuery(String comboQuery) {
        this._comboQuery = comboQuery;
    }

    public Object getRealValue() {
        Object val = _realValue;
        if (val != null && val instanceof Object[]
                && "string".equals(_valueType)) {
            Object[] vals = (Object[]) val;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < vals.length; i++) {
                sb.append(vals[i]);
                if (i < vals.length - 1)
                    sb.append(_separator);
            }
            val = sb.toString();
            sb = null;
        }
        return val;
    }

    public void setRealValue(Object val) {
        if (val != null && val instanceof byte[])
            val = SerializationUtils.deserialize((byte[]) val);
        Object value = val;
        if (val != null && _multiple && "string".equals(_valueType)) {
            if (!(val instanceof Object[]))
                value = val.toString().split("\\" + _separator);
        }
        this._realValue = value;
        if (!this._combo || Strings.isBlank(_comboQuery))
            setRawValue(val);
    }

    @Override
    public void service(AuRequest request, boolean everError) {
        String cmd = request.getCommand();
        if (cmd.equals(Events.ON_CHANGE) || cmd.equals(Events.ON_CHANGING))
            _realValue = request.getData().get("value");
        super.service(request, everError);
    }

    @Override
    protected String coerceToString(Object value) {
        if (value instanceof Object[]) {
            Object[] vals = (Object[]) value;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < vals.length; i++) {
                sb.append(vals[i]);
                if (i < vals.length - 1)
                    sb.append(_separator);
            }
            return sb.toString();
        } else if (value != null) {
            return value.toString();
        } else
            return super.coerceToString(value);
    }

    /**
     * @return the pagingMold
     */
    public String getPagingMold() {
        return _pagingMold;
    }

    /**
     * @param pagingMold the pagingMold to set
     */
    public void setPagingMold(String pagingMold) {
        this._pagingMold = pagingMold;
    }

    /**
     * @return the pagingStyle
     */
    public String getPagingStyle() {
        return _pagingStyle;
    }

    /**
     * @param pagingStyle the pagingStyle to set
     */
    public void setPagingStyle(String pagingStyle) {
        this._pagingStyle = pagingStyle;
    }

    /**
     * @return the pagingAutohide
     */
    public boolean isPagingAutohide() {
        return _pagingAutohide;
    }

    /**
     * @param pagingAutohide the pagingAutohide to set
     */
    public void setPagingAutohide(boolean pagingAutohide) {
        this._pagingAutohide = pagingAutohide;
    }

    /**
     * @return the pagingDetailed
     */
    public boolean isPagingDetailed() {
        return _pagingDetailed;
    }

    /**
     * @param pagingDetailed the pagingDetailed to set
     */
    public void setPagingDetailed(boolean pagingDetailed) {
        this._pagingDetailed = pagingDetailed;
    }

    /**
     * @return
     */
    public boolean isSizable() {
        return _sizable;
    }

    /**
     * @param sizable
     */
    public void setSizable(boolean sizable) {
        this._sizable = sizable;
    }

    /**
     * @return the span
     */
    public boolean isSpan() {
        return _span;
    }

    /**
     * @param span the span to set
     */
    public void setSpan(boolean span) {
        this._span = span;
    }

    /**
     * @return the showPanel
     */
    public boolean isShowPanel() {
        return _showPanel;
    }

    /**
     * @param showPanel the showPanel to set
     */
    public void setShowPanel(boolean showPanel) {
        this._showPanel = showPanel;
    }

    /**
     * @return the frozenColumns
     */
    public int getFrozenColumns() {
        return _frozenColumns;
    }

    /**
     * @param frozenColumns the frozenColumns to set
     */
    public void setFrozenColumns(int frozenColumns) {
        this._frozenColumns = frozenColumns;
    }

    /**
     * @return the export
     */
    public boolean isExport() {
        return _export;
    }

    /**
     * @param export the export to set
     */
    public void setExport(boolean export) {
        this._export = export;
    }

    /**
     * @return the checkmark
     */
    public boolean isCheckmark() {
        return _checkmark;
    }

    /**
     * @param checkmark the checkmark to set
     */
    public void setCheckmark(boolean checkmark) {
        this._checkmark = checkmark;
    }

    /**
     * @return the multiple
     */
    public boolean isMultiple() {
        return _multiple;
    }

    /**
     * @param multiple the multiple to set
     */
    public void setMultiple(boolean multiple) {
        this._multiple = multiple;
    }

    /**
     * @return the oddRowSclass
     */
    public String getOddRowSclass() {
        return _oddRowSclass;
    }

    /**
     * @param oddRowSclass the oddRowSclass to set
     */
    public void setOddRowSclass(String oddRowSclass) {
        this._oddRowSclass = oddRowSclass;
    }

    /**
     * @return the position
     */
    public String getPosition() {
        return _position;
    }

    /**
     * @param position the position to set
     */
    public void setPosition(String position) {
        this._position = position;
    }

    /**
     * @return the showGroupCount
     */
    public boolean isShowGroupCount() {
        return _showGroupCount;
    }

    /**
     * @param showGroupCount the showGroupCount to set
     */
    public void setShowGroupCount(boolean showGroupCount) {
        this._showGroupCount = showGroupCount;
    }

    /**
     * @return the condition
     */
    public String getCondition() {
        return _condition;
    }

    /**
     * @param condition the condition to set
     */
    public void setCondition(String condition) {
        this._condition = condition;
    }

    /**
     * @return
     */
    public String getFor() {
        return _for;
    }

    /**
     * @param _for
     */
    public void setFor(String _for) {
        this._for = _for;
    }

    /**
     * @return
     */
    public boolean isShowRowNumbers() {
        return _showRowNumbers;
    }

    /**
     * @param showRowNumbers
     */
    public void setShowRowNumbers(boolean showRowNumbers) {
        this._showRowNumbers = showRowNumbers;
    }

    /**
     * @return
     */
    public String getGroup() {
        return _group;
    }

    /**
     * @param group
     */
    public void setGroup(String group) {
        this._group = group;
    }

    /**
     * @return the orderBy
     */
    public String getOrderBy() {
        return _orderBy;
    }

    /**
     * @param orderBy the orderBy to set
     */
    public void setOrderBy(String orderBy) {
        this._orderBy = orderBy;
    }

    /**
     * @return the _levelBy
     */
    public String getLevelBy() {
        return _levelBy;
    }

    /**
     * @param levelBy the _levelBy to set
     */
    public void setLevelBy(String levelBy) {
        this._levelBy = levelBy;
    }

    public String getTitle() {
        return _title;
    }

    public void setTitle(String title) {
        this._title = title;
    }

    public String getPanelWidth() {
        return _panelWidth;
    }

    public void setPanelWidth(String panelWidth) {
        this._panelWidth = panelWidth;
    }

    public String getPanelHeight() {
        return _panelHeight;
    }

    public void setPanelHeight(String panelHeight) {
        this._panelHeight = panelHeight;
    }

    public String getEntity() {
        return _entity;
    }

    public void setEntity(String entity) {
        _entity = entity;
    }

    public String getMapping() {
        return _mapping;
    }

    public void setMapping(String mapping) {
        this._mapping = mapping;
    }

    public int getPageSize() {
        return _pageSize;
    }

    public void setPageSize(int pageSize) {
        this._pageSize = pageSize;
    }

    public boolean isImmediate() {
        return true;
    }

    public void setInvisibleColumns(String invisibleColumns) {
        this._invisibleColumns = invisibleColumns;
    }

    public String getInvisibleColumns() {
        return _invisibleColumns;
    }

    public boolean isSizedByContent() {
        return _sizedByContent;
    }

    public void setSizedByContent(boolean sizedByContent) {
        this._sizedByContent = sizedByContent;
    }

    public boolean isAutocomplete() {
        return _autocomplete;
    }

    public void setAutocomplete(boolean autocomplete) {
        this._autocomplete = autocomplete;
    }

    public String getRowStyle() {
        return _rowStyle;
    }

    public void setRowStyle(String rowStyle) {
        this._rowStyle = rowStyle;
    }

    public String getHeadStyle() {
        return _headStyle;
    }

    public void setHeadStyle(String headStyle) {
        this._headStyle = headStyle;
    }

    public String getAuxHeadStyle() {
        return _auxHeadStyle;
    }

    public void setAuxHeadStyle(String auxHeadStyle) {
        this._auxHeadStyle = auxHeadStyle;
    }

    public String getFootStyle() {
        return _footStyle;
    }

    public void setFootStyle(String footStyle) {
        this._footStyle = footStyle;
    }

    public String getFrozenStyle() {
        return _frozenStyle;
    }

    public void setFrozenStyle(String frozenStyle) {
        this._frozenStyle = frozenStyle;
    }

    /**
     * @return the useQueryResult
     */
    public boolean isUseQueryResult() {
        return _useQueryResult;
    }

    /**
     * @param useQueryResult the useQueryResult to set
     */
    public void setUseQueryResult(boolean useQueryResult) {
        this._useQueryResult = useQueryResult;
    }

    /**
     * @return the init
     */
    public String getInit() {
        return _init;
    }

    /**
     * @param init the init to set
     */
    public void setInit(String init) {
        this._init = init;
    }


    /**
     * @return the checkall
     */
    public boolean isCheckall() {
        return _checkall;
    }

    /**
     * @param checkall the checkall to set
     */
    public void setCheckall(boolean checkall) {
        this._checkall = checkall;
    }
}
